#include "TCPNetwork.h"
#include "Defines.h"

TCPNetwork::TCPNetwork()
{
	clntLen = 0;
	max_conns = 0;
}

TCPNetwork::~TCPNetwork()
{
}


void TCPNetwork::DieWithError(char *errorMessage)
{
//	gotoxy(0,WhereToPrintNetworkInfo);
	fprintf(stderr,"%s: %d\n",
	errorMessage, WSAGetLastError());
	exit(0);
}

void TCPNetwork::setUpNetworkServer()
{

//	gotoxy(0,WhereToPrintNetworkInfo);
    echoServPort = 7777;

    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */
    {
        fprintf(stderr, "WSAStartup() failed");
        exit(1);
    }

    // Create socket for incoming connections
    if ((listenSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
        DieWithError("listen() failed");

    // Construct local address structure
    memset(&echoServAddr, 0, sizeof(echoServAddr));   /* Zero out structure */
	memset(&echoBuffer, 0, sizeof(echoBuffer));   /* Zero out structure */
    echoServAddr.sin_family = AF_INET;                /* Internet address family */
    echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    echoServAddr.sin_port = htons(echoServPort);      /* Local port */

    /* Bind to the local address */
	if (bind(listenSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0){
        DieWithError("bind() failed");
	}

	// listen for incoming connection
	if (listen(listenSock, 5) != 0) {
		DieWithError("listen() failed");
	}

	// Set the size of the in-out parameter
	clntLen = sizeof(echoClntAddr);

	if( (servSock[max_conns] = accept(listenSock, (struct sockaddr *) &echoClntAddr, &clntLen)) == INVALID_SOCKET ){
		DieWithError("accept() failed");
	}
	++max_conns;




}

void TCPNetwork::serverRecvDate(char ** board)
{
//	gotoxy(0,WhereToPrintNetworkInfo);
	// Set the size of the in-out parameter
	clntLen = sizeof(echoClntAddr);



	if(max_conns > 0)
	{
		for(int i = 0; i < max_conns; ++i)
		{
				serverRecvDate(i, board);
		}
	}

}
void TCPNetwork::serverSendDate(char ** board){

//	gotoxy(0,WhereToPrintNetworkInfo);
	// Set the size of the in-out parameter
	clntLen = sizeof(echoClntAddr);

	if(max_conns > 0)
	{
		for(int i = 0; i < max_conns; ++i)
		{
//			if (FD_ISSET(servSock[i], &writefds))
//			{
				serverSendDate(i, board);
//			}
		}
	}

}

void TCPNetwork::serverRecvDate(int i, char ** board)
{
//	gotoxy(0,WhereToPrintNetworkInfo);
	// Receive message from client== INVALID_SOCKET 
	if ((recvMsgSize = recv(servSock[i], recvBuffer, RCVBUFSIZE, 0)) < 0) {
		printf("recv() failed: %d",WSAGetLastError());
	} else {

		for(int y = 0, count = 0; y < HEIGHT; ++y)
		{
			for(int x = 0; x < WIDTH; ++x, ++count)
			{
				(board[y][x]) = recvBuffer[count];
			}
		}
		// printf("DEBUG size  == %d\n", recvMsgSize);
		recvBuffer[recvMsgSize] = '\0';
//		printf("Received message from: %s\n\n", recvBuffer);
		memset(&recvBuffer, 0, sizeof(recvBuffer)); // Zero out the buffer
	}
}

void TCPNetwork::serverSendDate(int i, char ** board)
{
//	gotoxy(0,WhereToPrintNetworkInfo);

		for(int y = 0, count = 0; y < HEIGHT; ++y)
		{
			for(int x = 0; x < WIDTH; ++x, ++count)
			{
				echoBuffer[count] = (board[y][x]);
			}
		}


	// Receive message from client== INVALID_SOCKET 
	if ((recvMsgSize = send(servSock[i], echoBuffer, strlen(echoBuffer), 0)) < 0) {
		printf("sent() failed: %d",WSAGetLastError());

	} else {



//		gotoxy(0,WhereToPrintNetworkInfo);
		// printf("DEBUG size  == %d\n", recvMsgSize);
		echoBuffer[recvMsgSize] = '\0';
	//	printf("Sent message from: %s\n\n", echoBuffer);
		memset(&echoBuffer, 0, sizeof(echoBuffer)); // Zero out the buffer
	}

}

void TCPNetwork::setUpNetworkClint(char * IPInput){
	
//	gotoxy(0,WhereToPrintNetworkInfo);
	servPort = 7777;

	//cin.ignore();
//	changePortIP();
	
	if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */
	{
		fprintf(stderr, "WSAStartup() failed");
		exit(1);
	}

	// Create socket for incoming connections
	if ((clintSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
		DieWithError("socket() failed");

	// Construct local address structure
	memset(&clntAddr, 0, sizeof(clntAddr));   /* Zero out structure */
	memset(&echoBuffer, 0, sizeof(echoBuffer));   /* Zero out structure */
	clntAddr.sin_family = AF_INET;                /* Internet address family */				
	clntAddr.sin_addr.s_addr = inet_addr(IPInput); /* Any incoming interface */
	clntAddr.sin_port = htons(servPort);      /* Local port */

	// Set the size of the in-out parameter
	clntLen = sizeof(clntAddr);

	if(connect(clintSock, (struct sockaddr *) &clntAddr, clntLen ) == SOCKET_ERROR){
		DieWithError("connect() failed");
	}

	// Set the size of the in-out parameter
	clntLen = sizeof(echoClntAddr);
}

void TCPNetwork::clintSendDate(char ** board){

	// Set the size of the in-out parameter
	clntLen = sizeof(echoClntAddr);

			
	for(int y = 0, count = 0; y < HEIGHT; ++y)
	{
		for(int x = 0; x < WIDTH; ++x, ++count)
		{
				echoBuffer[count] = (board[y][x]);
		}
	}

	// send message to client
	if ((recvMsgSize = send(clintSock, echoBuffer, strlen(echoBuffer), 0)) < 0) {
		DieWithError("send() failed");
	}

//	gotoxy(0,WhereToPrintNetworkInfo);
	echoBuffer[recvMsgSize] = '\0';

	//printf("sent message: %c\n", echoBuffer);
	memset(&echoBuffer, 0, sizeof(echoBuffer)); // Zero out the buffer
	//getch();

}
void TCPNetwork::clintRecvDate(char ** board){

	// Set the size of the in-out parameter
	clntLen = sizeof(echoClntAddr);

	// recv message from server
	if ((recvMsgSize = recv(clintSock, recvBuffer, RCVBUFSIZE, 0)) < 0) {
		DieWithError("recv() failed");
	}else{

	for(int y = 0, count = 0; y < HEIGHT; ++y)
	{
		for(int x = 0; x < WIDTH; ++x, ++count)
		{
			(board[y][x]) = recvBuffer[count];
		}
	}

//	gotoxy(0,WhereToPrintNetworkInfo);
	recvBuffer[recvMsgSize] = '\0';

	//printf("recv message: %s\n", recvBuffer);
	memset(&recvBuffer, 0, sizeof(recvBuffer)); // Zero out the buffer
	}
}

void TCPNetwork::changePortIP(){

//	gotoxy(0,WhereToPrintNetworkInfo);
	cout << "Ip add: ";
	cin.getline(Ipinput,16, '\n');
	cout << "DEBUG ip = " << Ipinput << "Port = " << servPort << endl;
}